﻿using System;
using System.Collections.Generic;
using CID.Domain.Infrastructure;
using NailsFramework.Persistence;
using CID.Domain.Exceptions;

namespace CID.Domain.Audit
{
    public abstract class ParameterDeploymentLog : Model<ParameterDeploymentLog>, IParameterDeploymentLog
    {
        private static Dictionary<ParameterType, Func<IParameterValue, string>> serializiationMethodsMap = new Dictionary<ParameterType, Func<IParameterValue, string>>();
        static ParameterDeploymentLog()
        {
            serializiationMethodsMap.Add(ParameterType.Boolean, x => ParameterValueSerializer.Serialize(x.BooleanValue));
            serializiationMethodsMap.Add(ParameterType.DateTime, x => ParameterValueSerializer.Serialize(x.DateTimeValue));
            serializiationMethodsMap.Add(ParameterType.Decimal, x => ParameterValueSerializer.Serialize(x.DecimalValue));
            serializiationMethodsMap.Add(ParameterType.Integer, x => ParameterValueSerializer.Serialize(x.IntegerValue));
            serializiationMethodsMap.Add(ParameterType.String, x => ParameterValueSerializer.Serialize(x.StringValue));
            serializiationMethodsMap.Add(ParameterType.UniqueIdentifier, x => ParameterValueSerializer.Serialize(x.UniqueIdentifierValue));
            serializiationMethodsMap.Add(ParameterType.Xml, x => ParameterValueSerializer.Serialize(x.XmlValue));
        }

        public virtual int Id { get; private set; }
        public virtual IVersionDeploymentLog VersionDeploymentLog { get; private set; }
        public virtual string ParameterName { get; private set; }
        public virtual string ParameterValue { get; private set; }

        protected ParameterDeploymentLog()
        { 
        }

        protected ParameterDeploymentLog(IVersionDeploymentLog versionDeploymentLog, IParameterValue parameterValue) : this()
        {
            VersionDeploymentLog = versionDeploymentLog;
            ParameterName = parameterValue.Parameter.Name;
            ParameterValue = serializiationMethodsMap[parameterValue.Parameter.Type](parameterValue);
        }
    }

    public class ActivationParameterDeploymentLog : ParameterDeploymentLog, IActivationParameterDeploymentLog
    {
        protected ActivationParameterDeploymentLog() : base() { }

        internal ActivationParameterDeploymentLog(IVersionDeploymentLog versionDeploymentLog, IParameterValue parameterValue)
            : base(versionDeploymentLog, parameterValue)
        {
            if (!(parameterValue.Parameter.Template is IActivationTemplate)) throw new InvalidParameterAssignmentTemplateException("Activation");
        }
    }

    public class DeactivationParameterDeploymentLog : ParameterDeploymentLog, IDeactivationParameterDeploymentLog
    {
        protected DeactivationParameterDeploymentLog() : base() { }

        internal DeactivationParameterDeploymentLog(IVersionDeploymentLog versionDeploymentLog, IParameterValue parameterValue)
            : base(versionDeploymentLog, parameterValue)
        {
            if (!(parameterValue.Parameter.Template is IDeactivationTemplate)) throw new InvalidParameterAssignmentTemplateException("Deactivation");
        }
    }

    public class DeploymentParameterDeploymentLog : ParameterDeploymentLog, IDeploymentParameterDeploymentLog
    {
        protected DeploymentParameterDeploymentLog() : base() { }

        internal DeploymentParameterDeploymentLog(IVersionDeploymentLog versionDeploymentLog, IParameterValue parameterValue)
            : base(versionDeploymentLog, parameterValue)
        {
            if (!(parameterValue.Parameter.Template is IDeploymentTemplate)) throw new InvalidParameterAssignmentTemplateException("Deployment");
        }
    }
}
